/*
 * Copyright (c) 2010 k.schulz , c.mueller
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * The Software shall be used for Good, not Evil.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package de.altitudecustomcommands;


import de.altitude.cimuelle.Config;
import de.altitude.cimuelle.commandhandles.*;
import de.altitude.cimuelle.utils.ServerUtils;
import org.apache.log4j.Logger;

import javax.naming.ConfigurationException;
import java.util.Map;


/**
 * This class provides methods to execute custom commands.
 * cimuelle: did redesigning / refactoring
 *
 * @author k.schulz
 * @author c.mueller
 */
public class commandHandler {

    private playerHandler playerList = null;
    private serverInformations server = null;

    public static Thread timerMessage;

    private static final Logger LOGGER = Logger.getLogger("commandHandler");

    /**
     * Construct a new commandHandler.
     */
    public commandHandler() {
        this.playerList = new playerHandler();

        try {
            this.server = new serverInformations();
            timerMessage = new Thread() {
                public final boolean timerMonitor = true;

                @Override
                public void run() {
                    //noinspection ConstantConditions
                    while (timerMonitor) {
                        try {
                            LOGGER.info("Starting monitoring thread.");
                            sleep(Integer.parseInt(Config.getInstance().getConfig("monitoringIntervall", "300")) * 1000);
                            if (Config.getInstance().isDebug()) {
                                LOGGER.info("Recheck the running threads for periodic messages.");
                            }
                            for (int i = 0; i < server.getServerNumber(); i++) {
                                server.checkTimerMessage(String.valueOf(server.getServer(i).getPort()));
                            }
                        } catch (InterruptedException e) {
                            LOGGER.info("Stopping monitoring thread.");
                            break;
                        } catch (ConfigurationException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            timerMessage.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * This method executes one command as discriped in the customCommads.txt
     *
     * @param json A JSONObject which represents a custom command.
     * @return Returns true if a command is executed successfully.
     */
    public boolean executeCommand(Map json) {
        try {
            String port = String.valueOf(json.get("port"));
            int playerId;
            if (json.containsKey("player")) {
                playerId = Integer.parseInt(String.valueOf(json.get("player")));
            } else {
                playerId = -1;
            }

            final Object type = json.get("type");
            if ("clientAdd".equals(type)) {
                new TypeClientAdd(json, playerList);
            } else if ("teamChange".equals(type)) {
                new TypeTeamChange(port, playerId, json, playerList);
            } else if ("clientNicknameChange".equals(type)) {
                new TypeClientOperations(playerList, server).typeClientNicknameChange(json);
            } else if ("clientRemove".equals(type)) {
                new TypeClientOperations(playerList, server).typeClientRemove(json);
            } else if ("customCommand".equals(type)) {
                //typeCustomCommand(json);
            } else if ("chat".equals(type)) {
                String chatString = (String) json.get("message");
                new TypeChatHandle(playerList, server).typeChat(port, playerId, chatString);
            } else if ("structureDestroy".equals(type)) {
                new TypeStructureHandler(playerList).typeStructureDestroy(json, port, playerId);
            } else if ("structureDamage".equals(type)) {
                new TypeStructureHandler(playerList).typeStructureDamage(json, port, playerId);
            } else if ("mapChange".equals(type)) {
                new TypeMapChange(playerList, server).typeMapChange(port, json);
            } else if ("kill".equals(type)) {
                new TypeClientOperations(playerList, server).typeClientKill(json, port, playerId);
            } else if ("assist".equals(type)) {
                new TypeClientOperations(playerList, server).typeClientAssist(json, port, playerId);
            } else if ("goal".equals(type)) {
                new TypeClientOperations(playerList, server).typeGoal(json, port, playerId);
            } else if ("consoleCommandExecute".equals(type)) {
                new TypeConsoleHandler(playerList, server).typeConsoleCommandExecute(port, json);
            } else if ("logServerStatus".equals(type)) {
                ServerUtils.typeLogServerStatus(json, port, playerList);
            } else if ("spawn".equals(type)) {
                new TypeClientOperations(playerList, server).typeSpawn(port, playerId, json);
            } else if ("objectiveGameStart".equals(type)) {
                new TypeObjectiveHandler(playerList, server).typeGameStart(port);
            } else if ("objectiveGameEnd".equals(type)) {
                new TypeObjectiveHandler(playerList, server).typeGameStop(port, json);
            } else if ("demolitionChargePlanted".equals(type)) {
                new TypeMiscHandler(playerList, server).typeDemolitionChargePlanted(port);
            } else {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error(e, e);
            return false;
        }
        return true;
    }


}
